/*
 * @Author: shiguo
 * @Date: 2022-06-09 10:42:37
 * @LastEditors: shiguo
 * @LastEditTime: 2022-09-07 18:28:02
 * @FilePath: /@aks-dev/taro-h5/lib/SignaturePadCanvas/index.tsx
 */
import * as React from 'react'
import SignaturePad, { Options } from 'signature_pad'
import { SignaturePadCanvasProps } from '../../types/SignaturePadCanvas'




export const SignaturePadCanvas: React.ForwardRefExoticComponent<
    React.PropsWithoutRef<SignaturePadCanvasProps>
    & React.RefAttributes<SignaturePadCanvasProps.RefAttributes>
>
    = React.forwardRef((props, ref) => {

        const canvasRef: React.MutableRefObject<HTMLCanvasElement> = React.useRef() as any
        const signaturePadRef: React.MutableRefObject<SignaturePad> = React.useRef() as any

        React.useImperativeHandle<unknown, SignaturePadCanvasProps.RefAttributes>(ref, () => ({
            getCanvas: () => canvasRef.current,
            getSignaturePad: () => signaturePadRef.current
        }), [])


        React.useEffect(() => {
            const options: Options = ignore(props,
                'beginStroke',
                'endStroke',
                'beforeUpdateStroke',
                'afterUpdateStroke',
                'style',
                'draggable')
            const signaturePad = new SignaturePad(canvasRef.current, options);
            signaturePadRef.current = signaturePad;
            resizeCanvas();
            signaturePad.on();
            window.addEventListener("resize", resizeCanvas);

            props.beginStroke && signaturePad.addEventListener("beginStroke", props.beginStroke); //可以添加监听配置
            props.endStroke && signaturePad.addEventListener("endStroke", props.endStroke);
            props.beforeUpdateStroke && signaturePad.addEventListener("beforeUpdateStroke", props.beforeUpdateStroke);
            props.afterUpdateStroke && signaturePad.addEventListener("afterUpdateStroke", props.afterUpdateStroke);

            return () => {
                window.removeEventListener("resize", resizeCanvas);
                signaturePad.off()

                props.beginStroke && signaturePad.removeEventListener("beginStroke", props.beginStroke);
                props.endStroke && signaturePad.removeEventListener("endStroke", props.endStroke);
                props.beforeUpdateStroke && signaturePad.removeEventListener("beforeUpdateStroke", props.beforeUpdateStroke);
                props.afterUpdateStroke && signaturePad.removeEventListener("afterUpdateStroke", props.afterUpdateStroke);
            }
        }, [props])


        const resizeCanvas = () => {
            let _canvas = canvasRef.current
            let _signaturePad = signaturePadRef.current
            const ratio = Math.max(window.devicePixelRatio || 1, 1);
            _canvas.width = _canvas.offsetWidth * ratio;
            _canvas.height = _canvas.offsetHeight * ratio;
            _canvas.getContext("2d")?.scale(ratio, ratio);
            _signaturePad.clear(); // otherwise isEmpty() might return incorrect value
        }



        // type  range = keyof Options        
        // type OmitUser = Omit<SignaturePadCanvasProps, keyof Options | 'beginStroke' | 'endStroke'>;
        return (
            <canvas
                ref={canvasRef}
                {...ignore(props,
                    'beginStroke',
                    'endStroke',
                    'beforeUpdateStroke',
                    'afterUpdateStroke'
                ) as React.DetailedHTMLProps<React.CanvasHTMLAttributes<HTMLCanvasElement>, HTMLCanvasElement>}
            />
        )
    })



const ignore:
    (target: object,
        ...keys: (keyof SignaturePadCanvasProps)[]) => object
    = (target, ...keys) => {
        const _target = Object.assign({}, target)
        keys.forEach(prop => delete _target[prop])
        return _target
    }
